package com.fineaiops.gateway.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fineaiops.gateway.bean.ServiceNode;
import com.fineaiops.gateway.service.ExpService;
import com.fineaiops.gateway.service.NodeService;
import com.fineaiops.gateway.util.JsonBuilder;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@CrossOrigin(origins = {"*", "null"})
public class GatewayController {
    private final Logger LOG = LoggerFactory.getLogger(getClass());
    @Autowired
    private NodeService nodeService;
    @Autowired
    private ExpService elasticService;

    @RequestMapping(value = "/test")
    public String greeter() {
        return "hello, world";
    }

    @RequestMapping(value = "/user")
    public String getUserInfo(@RequestParam(name = "name", defaultValue = "xxx") String name) {
        return "{\"name\": \""+ name +"\"}";
    }

    @RequestMapping("/serviceTopo")
    public String getServiceTopo() {
        return new JsonBuilder()
                .put("nodes", nodeService.getAllServiceNode())
                .put("edges", nodeService.getServiceEdges())
                .build()
                .toJSONString();
    }

    @RequestMapping("/exception_categories")
    public String getExceptionList(
            @RequestParam(name = "services") String[] services,
            @RequestParam(name = "levels") long[] levels,
            @RequestParam(name = "status") long[] status) {
        try {
            SearchHit[] hits = elasticService.getExceptionCategories(services, levels, status);
            ArrayList<JSONObject> res = new ArrayList<>();
            Map<String, ServiceNode> serviceMap = new HashMap<>();
            for (SearchHit hit: hits) {
                Map<String, Object> sourceMap = hit.getSourceAsMap();
                String serviceID = (String)sourceMap.get("service_id");
                if (!serviceMap.containsKey(serviceID)) {
                    serviceMap.put(serviceID, nodeService.getServiceByID(serviceID));
                }
                res.add(new JsonBuilder()
                        .put("id", hit.getId())
                        .put("type", "日志")
                        .put("level", (int)sourceMap.get("level") == 0?"紧急"
                                :(int)sourceMap.get("level")==1?"严重":"一般")
                        .put("status", sourceMap.get("status"))
                        .put("content",((String)sourceMap.get("content")).length()>100
                                ? ((String)sourceMap.get("content")).substring(0,100)+"..."
                                :sourceMap.get("content"))
                        .put("service",serviceMap.get(serviceID).getName())
                        .put("host","192.168.0.1")
                        .put("first", sourceMap.get("first_report_time"))
                        .put("last", sourceMap.get("last_report_time"))
                        .build());
            }
            return JSON.toJSONString(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

    @RequestMapping("/exception")
    public String getExceptionDetail(@RequestParam("id") String id) {
        try {
            JSONObject map = JSONObject.parseObject(elasticService.getExceptionCateByID(id).getSourceAsString());
            JSONArray logIDList = map.getJSONArray("log_ids");
            ArrayList logDetailList = new ArrayList<JSONObject>();
            for (Object logid: logIDList) {
                Map<String, Object> logMap = elasticService.getLogByID((String)logid).getSourceAsMap();
                String text = (String)logMap.get("content");
                logDetailList.add(new JsonBuilder().put("id", logid)
                        .put("content", text.length()>200 ?
                                text.substring(0,200)+"..."
                                :text)
                        .build());
            }
            String serviceID = (String)map.get("service_id");
            String serviceName = nodeService.getServiceByID(serviceID).getName();
            JSONObject res = new JsonBuilder()
                    .put("exception", new JsonBuilder()
                            .put("id", id)
                            .put("type", "日志")
                            .put("report_sum", logIDList.size()).put("host", "192.168.0.1")
                            .put("content", map.get("content"))
                            .put("service", serviceName)
                            .put("first_report_time", map.get("first_report_time"))
                            .put("last_report_time", map.get("last_report_time"))
                            .build())
                    .put("log_list", logDetailList)
                    .build();
            return JSON.toJSONString(res);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

    @RequestMapping("/relative_exception")
    public String getRelativeException(@RequestParam("id") String id) {
        try {
            Map<String,Object> map = elasticService.getExceptionCateByID(id).getSourceAsMap();
            String content = (String)map.get("content");
            String serviceID = (String)map.get("service_id");
            TreeMap<String, ArrayList<String>> relationMap = nodeService.getRelatedService(serviceID);
            ArrayList<JSONObject> res = new ArrayList<>();
            Map<String, ServiceNode> serviceMap = new HashMap<>();
            for (Map.Entry<String, ArrayList<String>> entry : relationMap.entrySet()) {
                SearchHit[] hits = elasticService.getRelativeExceptionByContent(content, entry.getValue());
                for (SearchHit hit : hits) {
                    Map<String, Object> sourceMap = hit.getSourceAsMap();
                    String text = (String)sourceMap.get("content");
                    text = text.length()>100?text.substring(0,100)+"...":text;
                    String relativeServiceID =(String)sourceMap.get("service_id");
                    if (!serviceMap.containsKey(relativeServiceID)) {
                        serviceMap.put(relativeServiceID, nodeService.getServiceByID(relativeServiceID));
                    }
                    res.add(new JsonBuilder()
                            .put("id", hit.getId())
                            .put("type", "日志")
                            .put("relation",entry.getKey())
                            .put("content", text)
                            .put("service", serviceMap.get(relativeServiceID).getName())
                            .build());
                }
            }
            return JSON.toJSONString(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

}